package org.beetlframework.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 集合操作类，支持并集
 * 参考org.apache.commons.collections.CollectionUtils
 * @author 草原狼
 * @date 2016-10-5
 */
public class CollectionUtils {
	/** Constant to avoid repeated object creation */
    private static Integer INTEGER_ONE = new Integer(1);
	/**
     * Returns a {@link Collection} containing the union
     * of the given {@link Collection}s.
     * <p>
     * The cardinality of each element in the returned {@link Collection}
     * will be equal to the maximum of the cardinality of that element
     * in the two given {@link Collection}s.
     *
     * @param a  the first collection, must not be null
     * @param b  the second collection, must not be null
     * @return  the union of the two collections
     * @see Collection#addAll
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public static Collection union(final Collection a, final Collection b) {
        ArrayList list = new ArrayList();       
		Map mapa = getCardinalityMap(a);
        Map mapb = getCardinalityMap(b);
        Set elts = new HashSet(a);
        elts.addAll(b);
        Iterator it = elts.iterator();
        while(it.hasNext()) {
            Object obj = it.next();
            for(int i=0,m=Math.max(getFreq(obj,mapa),getFreq(obj,mapb));i<m;i++) {
                list.add(obj);
            }
        }
        return list;
    }
    
    /**
     * Returns a {@link Map} mapping each unique element in the given
     * {@link Collection} to an {@link Integer} representing the number
     * of occurrences of that element in the {@link Collection}.
     * <p>
     * Only those elements present in the collection will appear as
     * keys in the map.
     * 
     * @param coll  the collection to get the cardinality map for, must not be null
     * @return the populated cardinality map
     */
    public static Map<Object,Integer> getCardinalityMap(final Collection<Object> coll) {
        Map<Object,Integer> count = new HashMap<Object,Integer>();
        for (Iterator<Object> it = coll.iterator(); it.hasNext();) {
            Object obj = it.next();
            Integer c = (Integer) (count.get(obj));
            if (c == null) {
                count.put(obj,INTEGER_ONE);
            } else {
                count.put(obj,new Integer(c.intValue() + 1));
            }
        }
        return count;
    }
    
    private static final int getFreq(final Object obj, final Map<Object,Integer> freqMap) {
        Integer count = (Integer) freqMap.get(obj);
        if (count != null) {
            return count.intValue();
        }
        return 0;
    }
    
    /**
     * 测试并集操作
     * @param args
     */
    public static void main(String[] args){
    	List<Class<?>> list = new ArrayList<Class<?>>();
    	List<Class<?>> list2 = new ArrayList<Class<?>>();
    	try {
			list.add(Class.forName("org.beetlframework.util.ArrayUtil"));
			list.add(Class.forName("org.beetlframework.util.BeanUtil"));			
			list2.add(Class.forName("org.beetlframework.util.BeanUtil"));
			list2.add(Class.forName("org.beetlframework.util.CastUtil"));
			
			@SuppressWarnings("unchecked")
			List<Class<?>> list3 = ((List<Class<?>>)CollectionUtils.union(list, list2));
			System.out.println(list3);
		} catch (ClassNotFoundException e) {			
			e.printStackTrace();
		}
    	
    }
}
